package com.qingzhou.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.solon.service.impl.ServiceImpl;
import com.qingzhou.web.repository.dao.PatientDao;
import com.qingzhou.web.repository.dao.SurgeryDao;
import com.qingzhou.web.repository.entity.PatientEntity;
import com.qingzhou.web.repository.entity.SurgeryEntity;
import com.qingzhou.web.repository.mapper.SurgeryMapper;
import com.qingzhou.web.service.ConvertHelper;
import com.qingzhou.web.service.DataCheckLogService;
import com.qingzhou.web.service.EdcConstants;
import com.qingzhou.web.service.SurgeryService;
import com.qingzhou.web.service.impl.params.request.*;
import com.qingzhou.web.service.impl.params.vo.SurgeryVo;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.Tran;

import java.util.Date;
import java.util.List;
import java.util.Objects;

@Component
public class SurgeryServiceImpl extends ServiceImpl<SurgeryMapper, SurgeryEntity> implements SurgeryService {
    @Inject
    SurgeryDao surgeryDao;
    @Inject
    ConvertHelper convertHelper;
    @Inject
    DataCheckLogService dataCheckLogService;
    @Inject
    PatientDao patientDao;

    @Override
    @Tran
    public int add(SurgeryAddForm form) {
        Assert.isTrue(StrUtil.isNotEmpty(form.getPatientCode()), "患者编号不允许为空");
        SurgeryEntity entity = BeanUtil.copyProperties(form, SurgeryEntity.class);
        entity.setStatus("create");
        int row = surgeryDao.add(entity);

        if (ObjUtil.isNotNull(form.getOperationDate())) {
            this.updateVisitRemindDate(entity.getPatientCode(), DateUtil.offsetMonth(form.getOperationDate(), 1));
        }
        return row;
    }

    @Override
    public int delete(SurgeryDeleteForm form) {
        SurgeryEntity entity = surgeryDao.getById(form.getId());
        Assert.isTrue(ObjUtil.isNotNull(entity), "数据不见了");
        Assert.isTrue(StrUtil.equalsIgnoreCase("create", entity.getStatus()), "该状态不允许删除");

        return surgeryDao.delete(form.getId());
    }

    @Override
    public Page<SurgeryVo> page(Page<SurgeryEntity> page, SubTablePageForm form) {
        Page<SurgeryEntity> paginate = surgeryDao.getMapper().paginate(page, QueryWrapper.create()
                .in("patient_code", form.getPatientCodeList())
                .orderBy("create_time desc"));
        return convertHelper.convertSurgery(paginate);
    }

    @Override
    public SurgeryVo detail(SurgeryDetailForm form) {
        SurgeryEntity entity = surgeryDao.getById(form.getId());
        Assert.isTrue(ObjUtil.isNotNull(entity), "数据不见了");
        return convertHelper.convert(entity);
    }

    @Override
    @Tran
    public int edit(SurgeryEditForm form) {
        SurgeryEntity entity = surgeryDao.getById(form.getId());
        Assert.isTrue(ObjUtil.isNotNull(entity), "数据不见了");
        Assert.isTrue(StrUtil.equalsIgnoreCase("create", entity.getStatus()), "该状态不允许编辑");
        boolean isChangeOperationDate = DateUtil.compare(form.getOperationDate(), entity.getOperationDate()) != 0;

        BeanUtil.copyProperties(form, entity,"patientCode"); //患者编号不能变
        int update = surgeryDao.update(entity);

        // 如果编辑的是最新的一条，才更新拜访提醒时间，往后推3个月
        if (isChangeOperationDate && this.isLatestData(entity.getId())) {
            this.updateVisitRemindDate(entity.getPatientCode(), DateUtil.offsetMonth(form.getOperationDate(), 3));
        }

        return update;
    }

    @Override
    @Tran
    public int forceEdit(SurgeryForceEditForm form) {
        SurgeryEntity entity = surgeryDao.getById(form.getId());
        Assert.isTrue(ObjUtil.isNotNull(entity), "数据不见了");
        Assert.isTrue(StrUtil.equalsIgnoreCase("done", entity.getStatus()), "该状态不允许数据检查");
        boolean isChangeOperationDate = DateUtil.compare(form.getOperationDate(), entity.getOperationDate()) != 0;

        JSONObject diffContent = DataCheckLogServiceImpl.diff(entity, form, new String[]{});
        BeanUtil.copyProperties(form, entity,"patientCode"); //患者编号不能变
        int rows = surgeryDao.update(entity);

        if (rows > 0 && MapUtil.isNotEmpty(diffContent)) {
            DataCheckLogAddForm addForm = new DataCheckLogAddForm(EdcConstants.EDC_SURGERY, diffContent, entity.getPatientCode());
            dataCheckLogService.add(addForm);
        }

        // 如果编辑的是最新的一条，才更新拜访提醒时间，往后推3个月
        if (isChangeOperationDate && this.isLatestData(entity.getId())) {
            this.updateVisitRemindDate(entity.getPatientCode(), DateUtil.offsetMonth(form.getOperationDate(), 3));
        }

        return rows;
    }

    @Override
    @Tran
    public int done(SurgeryDoneForm form) {
        SurgeryEntity entity = surgeryDao.getById(form.getId());
        Assert.isTrue(ObjUtil.isNotNull(entity), "数据不见了");
        Assert.isTrue(StrUtil.equalsIgnoreCase("create", entity.getStatus()), "该状态不允许核实");
        boolean isChangeOperationDate = DateUtil.compare(form.getOperationDate(), entity.getOperationDate()) != 0;

        BeanUtil.copyProperties(form, entity,"patientCode"); //患者编号不能变
        entity.setStatus("done");
        int rows = surgeryDao.update(entity);

        // 如果编辑的是最新的一条，才更新拜访提醒时间，往后推3个月
        if (isChangeOperationDate && this.isLatestData(entity.getId())) {
            this.updateVisitRemindDate(entity.getPatientCode(), DateUtil.offsetMonth(form.getOperationDate(), 3));
        }

        return rows;
    }

    @Override
    public int stop(SurgeryStopForm form) {
        SurgeryEntity entity = surgeryDao.getById(form.getId());
        Assert.isTrue(ObjUtil.isNotNull(entity), "数据不见了");
        Assert.isTrue(!StrUtil.equalsIgnoreCase("stop", entity.getStatus()), "该状态不允许终止");

        entity.setStatus("stop");
        entity.setStopReason(form.getStopReason());
        return surgeryDao.update(entity);
    }

    private boolean isLatestData(Long id) {
        List<SurgeryEntity> createTimeDesc = this.getMapper()
                .selectListByQuery(QueryWrapper.create().orderBy("create_time desc")
                        .select("id")
                        .limit(1));
        SurgeryEntity surgeryEntity = createTimeDesc.get(0);
        return Objects.equals(surgeryEntity.getId(), id);
    }

    private void updateVisitRemindDate(String patientCode, Date nextRemindDate) {
        // 如果填了手术日期，就更新下次随访提醒日期
        if (ObjUtil.isNotNull(nextRemindDate)) {
            PatientEntity patient = patientDao.selectOneByPatientCode(patientCode);
            Assert.isTrue(ObjUtil.isNotNull(patient), "患者编号无效");
            patient.setVisitRemindDate(nextRemindDate);
            patientDao.update(patient);
        }
    }
}
